#include "../include/unrealstream.h"
#include "../include/unrealmap.h"
using namespace Glib;

UnrealStream::UnrealStream(const RefPtr<DataInputStream>& is, const RefPtr<DataOutputStream>& os)
{
    this->os = os;
    is->set_newline_type(DATA_STREAM_NEWLINE_TYPE_CR_LF);
    this->is = is;

    //ctor
}

UnrealStream::~UnrealStream()
{
    //dtor
}
string UnrealStream::nextMessage(){
    string message;
    is->read_line(message);
    fields.clear();
    int space = message.find(" ");
    if (space == string::npos)
        return MessName = message;
    MessName = message.substr(0, space);

    string field;
    string value;
    int lbracePos = space-1;
    int rbracePos = space;
    int spacePos  ;
newField:
    lbracePos = message.find('{', rbracePos);
    if (lbracePos == string::npos)
        return MessName;

    spacePos=message.find_first_of(" }{", lbracePos+1);
    if (message[spacePos]!=' ')
        throw new Gio::Error(Gio::Error::INVALID_DATA, ustring("space expected, but got: " + message[spacePos])) ;

    rbracePos = message.find_first_of("}{", spacePos);
    if (message[rbracePos]!='}')
        throw new Gio::Error(Gio::Error::INVALID_DATA, ustring("'}' expected, but got: " + message[rbracePos])) ;

    field = message.substr(lbracePos+1, spacePos-lbracePos-1);
    value = message.substr(spacePos+1, rbracePos-spacePos-1);

    fields.push_back(make_pair(field, value));
goto newField;
}



    bool UnrealStream::readUntil(string Message){
        while (nextMessage()!=Message);// not optimal yet, but that's not really neccesary, because it won't be used really oftn
    }

    void UnrealStream::putCommand(string cmd){
        os->put_string(cmd + "\r\n");
    }

    unsigned UnrealStream::matchVal(){
        return *((int*) MessName.c_str()) & 0x00ffFFff;
    }

    int UnrealStream::fieldCount(){
        return fields.size();
    }

string UnrealStream::currentMessage(){
    return MessName;
}


pair<string, string> UnrealStream::operator[](int pos){
    return fields[pos];
}


void UnrealStream::queueCommand(Command* cmd){
    commandQueue.push_back(cmd);
}

UnrealStream& UnrealStream::operator<<(Command& cmd){
    queueCommand(&cmd);
	return *this;
}

void UnrealStream::sendCommand(Command* cmd){
    os->put_string(cmd->make());
}

void UnrealStream::sendCommandDelete(Command* cmd){
	string c = cmd->make();
    os->put_string(c);
    delete cmd;
}

void UnrealStream::flushCommands(){
    for(vector<Command*>::iterator iter = commandQueue.begin(); iter<commandQueue.end(); iter++)
        sendCommandDelete(*iter);
    commandQueue.clear();
}



string Command::param(const char name[], UnrealPlace val){
    return ustring("{") + name + " "
         + ustring::compose("%1.%2", val.x/100, val.x%100) + ","
         + ustring::compose("%1.%2", val.y/100, val.y%100) + ","
         + ustring::compose("%1.%2", val.z/100, val.z%100) + "} ";
}

